[ C++で開発 ]

SolarisでGTK+を使う

GTK+はX Window System上のGUIツールキットの一つです。GNOMEデスクトップのベースとして使用されています。APIはC言語として提供されています。Solarisでは、バージョン9からGNOMEデスクトップが標準搭載されるようになりました。

GTK+の設定

Solaris 9環境でのGTK+

パッケージ名
glib gobject, gmodule glib
atk atk
pango pango, pangowin32
gtk2 gdk-win32, gdk_pixbuf, gtk
$ pkg-config --libs gtk+-2.0
-lgtk-x11-2.0 -lgdk-x11-2.0 -latk-1.0 -lgdk_pixbuf-2.0 -lm -lpangox-1.0 
-pango-1.0 -lgobject-2.0 -lgmodule-2.0 -ldl -lglib-2.0
$

C++プログラミング環境

GTK+は、オブジェクト指向風な設計をされていますが、あくまでC言語APIです。C++言語から使うのはインピーダンスミスマッチが大きいため、C++言語でラッピングされたライブラリを介して使用するのがよさそうです。

gtkmm

GTK+はC言語APIなので、C++から利用するときはちょっと面倒です。gtkmmは、GTK+をC++でラップするライブラリのひとつです。

GKT+バージョン 対応する
gtkmm
バージョン
対応する
libsigc++
バ―ジョン
活性度
2.0 2.0 1.2.x 最終更新2.0.2:2002年12月
2.2 2.2 1.2.x 最終更新2.2.12:2004年6月
2.4 2.4 2.0 最終更新2.4.5:2004年8月

Solaris標準搭載のGTK+バージョンは2.0なので、対応するgtkmmは事実上メンテナンスされてないのが気になるところです。CVSツリーにも、gtkmm2.0はないようです。

依存パッケージ libsigc++

gtkmmは、GTK+のほかに、libsigc++に依存しています。libsigc++は標準ではSolarisには搭載していないので、先にインストールする必要があります。

libsigc++のサイトから入手できます。

torutk$ cd work
work$ tar xvzf libsigc++-1.2.5.tar.gz
 :
work$ cd libsigc++-1.2.5
libsigc++-1.2.5$ CC=cc CXX=CC ./configure
 :
libsigc++-1.2.5$ make
 :
libsigc++-1.2.5$ make install
 :

以下のディレクトリにインストールされます。

/usr/local/include/sigc++-1.2/sigc++/*.h
          /lib/libsigc-1.2.a
          /lib/libsigc-1.2.la
          /lib/libsigc-1.2.so.*
          /lib/sigc++-1.2/include/sigcconfig.h
          /lib/pkgconfig/sigc++-1.2.pc

続くgtkmmのビルドにおいて、/usr/local以下にインストールしたパッケージ情報を伝えるために、環境変数PKG_CONFIG_PATH を定義します。

libsigc++-1.2.5$ export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig
libsigc++-1.2.5$

gtkmm 2.0のビルド

Sun Studio 9 C++コンパイラ(Sun C++ 5.6)でのビルドを行います。

torutk$ cd work
work$ tar xvjf gtkmm-2.0.2.tar.bz2
 :
work$ cd gtkmm-2.0.2
gtkmm-2.0.2$ export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig
gtkmm-2.0.2$ CC=cc CXX=CC ./configure
 :
gtkmm-2.0.2$ gmake
 :
ビルドエラー1

gtkmm-2.0.2/pango/pangomm/context.cc のコンパイルエラー

gtkmm-2.0.2$ make
 :
CC -DHAVE_CONFIG_H -DG_LOG_DOMAIN=\"pangomm\" -Dpangomm_COMPILATION -DG_DISABLE_
DEPRECATED -DGDK_DISABLE_DEPRECATED -DGDK_PIXBUF_DISABLE_DEPRECATED -DGTK_DISABL
E_DEPRECATED -I../../glib -I../../glib -I../../pango -I../../pango -I../../atk -
I../../atk -I../../gdk -I../../gdk -I../../gtk -I../../gtk -I/usr/local/lib/sigc
++-1.2/include -I/usr/local/include/sigc++-1.2 -I/usr/include/pango-1.0 -I/usr/i
nclude/glib-2.0 -I/usr/lib/glib-2.0/include -D_REENTRANT -I/usr/include/glib-2.0
 -I/usr/lib/glib-2.0/include -g -c context.cc  -KPIC -DPIC -o context.lo
"../../glib/glibmm/arrayhandle.h", line 187: Error: Ambiguous partial specializa
tion for Glib::Container_Helpers::TypeTraits<Glib::RefPtr<Pango::FontFace>>, Gli
b::Container_Helpers::TypeTraits and Glib::Container_Helpers::TypeTraits.
"../../glib/glibmm/arrayhandle.h", line 187: Error: Ambiguous partial specializa
tion for Glib::Container_Helpers::TypeTraits<Glib::RefPtr<Pango::FontFamily>>, G
lib::Container_Helpers::TypeTraits and Glib::Container_Helpers::TypeTraits.
"../../glib/glibmm/arrayhandle.h", line 187: Error: Ambiguous partial specializa
tion for Glib::Container_Helpers::TypeTraits<Glib::RefPtr<Pango::FontFamily>>, G
lib::Container_Helpers::TypeTraits and Glib::Container_Helpers::TypeTraits.
"../../glib/glibmm/arrayhandle.h", line 187: Error: Ambiguous partial specializa
tion for Glib::Container_Helpers::TypeTraits<Glib::RefPtr<Pango::FontFamily>>, G
lib::Container_Helpers::TypeTraits and Glib::Container_Helpers::TypeTraits.
"../../glib/glibmm/arrayhandle.h", line 191: Error: Ambiguous partial specializa
tion for Glib::Container_Helpers::TypeTraits<Glib::RefPtr<Pango::FontFamily>>, G
lib::Container_Helpers::TypeTraits and Glib::Container_Helpers::TypeTraits.
"context.cc", line 34:     Where: While specializing "Glib::ArrayHandle<Glib::Re
fPtr<Pango::FontFamily>, Glib::Container_Helpers::TypeTraits<Glib::RefPtr<Pango:
:FontFamily>>>".
"context.cc", line 34:     Where: Specialized in non-template code.
"../../glib/glibmm/arrayhandle.h", line 198: Error: Ambiguous partial specializa
tion for Glib::Container_Helpers::TypeTraits<Glib::RefPtr<Pango::FontFamily>>, G
lib::Container_Helpers::TypeTraits and Glib::Container_Helpers::TypeTraits.
"context.cc", line 34:     Where: While specializing "Glib::ArrayHandle<Glib::Re
fPtr<Pango::FontFamily>, Glib::Container_Helpers::TypeTraits<Glib::RefPtr<Pango:
:FontFamily>>>".
"context.cc", line 34:     Where: Specialized in non-template code.
"../../glib/glibmm/arrayhandle.h", line 199: Error: Ambiguous partial specializa
tion for Glib::Container_Helpers::TypeTraits<Glib::RefPtr<Pango::FontFamily>>, G
lib::Container_Helpers::TypeTraits and Glib::Container_Helpers::TypeTraits.
"context.cc", line 34:     Where: While specializing "Glib::ArrayHandle<Glib::Re
fPtr<Pango::FontFamily>, Glib::Container_Helpers::TypeTraits<Glib::RefPtr<Pango:
:FontFamily>>>".
"context.cc", line 34:     Where: Specialized in non-template code.
"../../glib/glibmm/arrayhandle.h", line 209: Error: Ambiguous partial specializa
tion for Glib::Container_Helpers::TypeTraits<Glib::RefPtr<Pango::FontFamily>>, G
lib::Container_Helpers::TypeTraits and Glib::Container_Helpers::TypeTraits.
"context.cc", line 34:     Where: While specializing "Glib::ArrayHandle<Glib::Re
fPtr<Pango::FontFamily>, Glib::Container_Helpers::TypeTraits<Glib::RefPtr<Pango:
:FontFamily>>>".
"context.cc", line 34:     Where: Specialized in non-template code.
"../../glib/glibmm/arrayhandle.h", line 236: Error: Ambiguous partial specializa
tion for Glib::Container_Helpers::TypeTraits<Glib::RefPtr<Pango::FontFamily>>, G
lib::Container_Helpers::TypeTraits and Glib::Container_Helpers::TypeTraits.
"context.cc", line 34:     Where: While specializing "Glib::ArrayHandle<Glib::Re
fPtr<Pango::FontFamily>, Glib::Container_Helpers::TypeTraits<Glib::RefPtr<Pango:
:FontFamily>>>".
"context.cc", line 34:     Where: Specialized in non-template code.
"../../glib/glibmm/arrayhandle.h", line 236: Error: Ambiguous partial specializa
tion for Glib::Container_Helpers::TypeTraits<Glib::RefPtr<Pango::FontFamily>>, G
lib::Container_Helpers::TypeTraits and Glib::Container_Helpers::TypeTraits.
"context.cc", line 34:     Where: While specializing "Glib::ArrayHandle<Glib::Re
fPtr<Pango::FontFamily>, Glib::Container_Helpers::TypeTraits<Glib::RefPtr<Pango:
:FontFamily>>>".
"context.cc", line 34:     Where: Specialized in non-template code.
"../../glib/glibmm/arrayhandle.h", line 187: Error: Ambiguous partial specializa
tion for Glib::Container_Helpers::TypeTraits<Glib::RefPtr<Pango::FontFamily>>, G
lib::Container_Helpers::TypeTraits and Glib::Container_Helpers::TypeTraits.
"context.cc", line 41: Error: Could not find a match for Glib::ArrayHandle<Glib:
:RefPtr<Pango::FontFamily>, Glib::Container_Helpers::TypeTraits<Glib::RefPtr<Pan
go::FontFamily>>>::ArrayHandle<Glib::ArrayHandle<Glib::RefPtr<Pango::FontFamily>
, Glib::Container_Helpers::TypeTraits<Glib::RefPtr<Pango::FontFamily>>>::Cont>(_
PangoFontFamily**, int, Glib::OwnershipType) needed in Pango::Context::list_fami
lies() const.
"context.cc", line 105: Warning (Anachronism): Assigning void(*)(void*,void*) to
 extern "C" void(*)(void*,void*).
12 Error(s) and 1 Warning(s) detected.
gmake[4]: *** [context.lo] Error 1
gmake[4]: Leaving directory `/export/home/toru/work/gtkmm-2.0.2/pango/pangomm'
gmake[3]: *** [all-recursive] Error 1
gmake[3]: Leaving directory `/export/home/toru/work/gtkmm-2.0.2/pango/pangomm'
gmake[2]: *** [all-recursive] Error 1
gmake[2]: Leaving directory `/export/home/toru/work/gtkmm-2.0.2/pango'
gmake[1]: *** [all-recursive] Error 1
gmake[1]: Leaving directory `/export/home/toru/work/gtkmm-2.0.2'
gmake: *** [all-recursive-am] Error 2
gtkmm-2.0.2$

エラー発生個所は、gtkmm-2.0.2/glib/glibmm/containerhandler_shared.h の以下の定義です。テンプレートの宣言で、struct TypeTraits<T*> と struct TypeTraits<const T*> の2つがある場合、Sun Studio C++コンパイラでは、const有り、無しどちらのテンプレート宣言を適用するか決定できないのでエラーになるようです。

namespace Glib {
namespace Container_Helpers {

  // :

template <class T> struct TypeTraits {
  typedef T CppType;
  typedef T CType;
  typedef T CTypeNonConst;

  static CType   to_c_type(const CppType& item) {return item;}
  static CppType to_cpp_type(const CType& item) {return item;}
  static void    release_c_type(const CType&) {}
};

template <class T> struct TypeTraits<T*> {
  typedef T * CppType;
  typedef typename T::BaseObjectType * CType;
  typedef typename T::BaseObjectType * CTypeNonConst;

  static CType to_c_type(CppType ptr) { return Glib::unwrap(ptr); }
  static CType to_c_type(CType ptr) { return ptr; }
  static CppType to_cpp_type(CType ptr) { return Glib::wrap(ptr, false); }
  static void release_c_type(CType ptr) { 
    GTKMM_DEBUG_UNREFERENCE(0, ptr);
    g_object_unref(ptr);
  }
};

template <class T> struct TypeTraits<const T*> {
  typedef T * CppType;
  typedef typename T::BaseObjectType * CType;
  typedef typename T::BaseObjectType * CTypeNonConst;

  static CType to_c_type(CppType ptr) { return Glib::unwrap(ptr); }
  static CType to_c_type(CType ptr) { return ptr; }
  static CppType to_cpp_type(CType ptr) { return Glib::wrap(ptr, false); }
  static void release_c_type(CType ptr) { 
    GTKMM_DEBUG_UNREFERENCE(0, ptr);
    g_object_unref(const_cast<CTypeNonConst>(ptr));
  }
};

// :

} // namespace Container_Helpers
} // namespace Glib

安直な回避策として、<const T*>のテンプレート宣言の方をコメントアウトします。上記に示したstruct TypeTraits<const T*>ともう1箇所struct TypeTraits<Glib::RefPtr<const T> >の2箇所をコメントアウトしてみました。(自信ない)

ビルドエラー2

gtkmm-2.0.2/gtk/gtkmm/iconfactory.ccのコンパイルエラー

gtk_icon_size_lookupのプロトタイプ宣言が見つからないとエラーになります。/usr/include/gtk-2.0/gtk/gtkiconfactory.h を見ると、

#ifdef GTK_MULTIHEAD_SAFE
gboolean gtk_icon_size_lookup (GtkIconSize size, gint *width, gint *height);
#endif

となっています。

回避策として、configure時にGTK_MULTIHEAD_SAFEを定義するようにします。

gtkmm-2.0.2$ CC=cc CXX=CC CPPFLAGS=-DGTK_MULTIHEAD_SAFE ./configure
 :
gtkmm-2.0.2$ gmake
 :
ビルドエラー3

gtkmm-2.0.2/gtk/gtkmm/treeview.cc のコンパイルエラー

gtkmm-2.0.2$ gmake
 :
CC -DHAVE_CONFIG_H -DG_LOG_DOMAIN=\"gtkmm\" -Dgtkmm_COMPILATION -DG_DISABLE_DEPR
ECATED -DGDK_DISABLE_DEPRECATED -DGDK_PIXBUF_DISABLE_DEPRECATED -DGTK_DISABLE_DE
PRECATED -I../../glib -I../../glib -I../../pango -I../../pango -I../../atk -I../
../atk -I../../gdk -I../../gdk -I../../gtk -I../../gtk -I/usr/local/lib/sigc++-1
.2/include -I/usr/local/include/sigc++-1.2 -I/usr/include/gtk-2.0 -I/usr/lib/gtk
-2.0/include -I/usr/include/atk-1.0 -I/usr/include/pango-1.0 -I/usr/openwin/incl
ude -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -D_REENTRANT -I/usr/incl
ude/glib-2.0 -I/usr/lib/glib-2.0/include -DGTK_MULTIHEAD_SAFE -g -c treeview.cc
 -KPIC -DPIC -o treeview.lo
 :
"treeview.cc", line 893: Error: Cannot assign void(*)(_GtkTreeView*,int) to exte
rn "C" int(*)(_GtkTreeView*,int).
 :
gtkmm-2.0.2$

下記の定義で型が合わないエラーが発生しています。

void TreeView_Class::class_init_function(void* g_class, void* class_data)
{
  :
  klass->select_cursor_row = &select_cursor_row_callback;
  :
}

gtkmm-2.0.2/gtk/gtkmm/private/treeview_p.hでの定義型と、GTKでの関数の型を比べると、

gtkmm-2.0.2/gtk/gtkmm/private/treeview_p.h
class TreeView_Class : public Glib::Class
{
  BaseClassType *const klass = static_cast<BaseClassType*>(g_class);
    :
  static void select_cursor_row_callback(GtkTreeView* self, gboolean p0);
    :
};

と戻り型がvoidとなっているのに対して、

/usr/include/gtk-2.0/gtk/gtktreeview.h
gboolean (* select_cursor_row) (GtkTreeView *tree_view, gboolean start_editing);

とGTK+2.0では戻り型がgbooleanになっています。

GCF

libsigc++ 2.0に依存しているので、libsigc++-2.0をビルドします。

libsigc++2.0

torutk$ cd work
work$ tar xvzf libsigc++-2.0.5.tar.gz
 :
work$ cd libsigc++-2.0.5
libsigc++-2.0.5$ CC=cc CXX=CC ./configure
 :
libsigc++-2.0.5$ make
 :
CC  -I. -I. -I.. -I.. -I..     -g -c -o test_slot.o test_slot.cc
"../sigc++/functors/slot.h", 行 122: エラー: 予期しない型名 "sigc::type_trait<in
t>::take" がありました.
"../sigc++/functors/slot.h", 行 123: エラー: "static sigc::internal::slot_call1<
foo, void, int>::call_it(sigc::internal::slot_rep*, const int&)" は値を返すこと
できません.
"../sigc++/functors/slot.h", 行 122: エラー: 予期しない型名 "sigc::type_trait<ch
ar>::take" がありました.
"../sigc++/functors/slot.h", 行 123: エラー: "static sigc::internal::slot_call1<
foo, void, char>::call_it(sigc::internal::slot_rep*, const char&)" は値を返すこ
はできません.
"../sigc++/functors/slot.h", 行 122: エラー: 予期しない型名 "sigc::type_trait<st
d::string &>::take" がありました.
"../sigc++/functors/slot.h", 行 123: エラー: "static sigc::internal::slot_call1<
foo, void, std::string &>::call_it(sigc::internal::slot_rep*, std::string &)" は
値を返すことはできません.
6 個のエラーが検出されました.
*** Error code 6
make: Fatal error: Command failed for target `test_slot.o'
Current working directory /export/home/toru/work/libsigc++-2.0.5/tests
*** Error code 1
make: Fatal error: Command failed for target `all-recursive'
Current working directory /export/home/toru/work/libsigc++-2.0.5
*** Error code 1
make: Fatal error: Command failed for target `all'
libsigc++-2.0.5$

This page is written by Toru TAKAHASHI.(torutk@02.246.ne.jp)